package com.doge.config;

/**
 * @program: doge
 * @description:
 * @author: Keyu Li
 * @create: 2021-12-01 19:23
 **/


import com.doge.config.realm.AdminRealm;
import com.doge.config.realm.WxRealm;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;


/*
* 权限和认证都是通过 Filter实现
*
* */

@Configuration
public class ShiroConfig {

    /*
     * ShiroFilterFactoryBean
     * 过滤器配置：
     *      --> SecurityManager --> Authenticator,Authorizer 通过管理器获取认证、授权器
     *      --> FilterChain 作用范围
     * */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 设置核心组件：SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 登录页面：
//        shiroFilterFactoryBean.setLoginUrl("/#/login");
        shiroFilterFactoryBean.setLoginUrl("/unauthc");
        /*
        * Filter是有序的，通过责任链依次执行，选择 LinkedHashmap
        *       --> anon匿名，authc认证，perms[x:x:x,...]权限
        * */
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 设置 无需认证的界面
        // 转到登录界面
        filterChainDefinitionMap.put("/unauthc","anon");
        // ADMIN
        // 登录
        filterChainDefinitionMap.put("/admin/auth/login","anon");
        filterChainDefinitionMap.put("/wx/auth/**","anon");
        // 数据库中添加 PermissionList
        filterChainDefinitionMap.put("/admin/role/insert/permission","anon");
        // WX
        // 商品
        filterChainDefinitionMap.put("/wx/home/**","anon");
        filterChainDefinitionMap.put("/wx/goods/**","anon");
        // 品牌
        filterChainDefinitionMap.put("/wx/brand/**","anon");
        // 类目
        filterChainDefinitionMap.put("/wx/catalog/**","anon");
        // 搜索
        filterChainDefinitionMap.put("/wx/search/**","anon");
        // 专题
        filterChainDefinitionMap.put("/wx/topic/**","anon");
        // 评论，post需要用户登录
        filterChainDefinitionMap.put("/wx/comment/post","authc");
        filterChainDefinitionMap.put("/wx/comment/**","anon");
        // 优惠券
        filterChainDefinitionMap.put("/wx/coupon/list","anon");
        // 图片
        filterChainDefinitionMap.put("/wx/storage/**","anon");
        // 注册
        filterChainDefinitionMap.put("/wx/auth/register","anon");
        // 商品详情界面 购物车数量统计
        filterChainDefinitionMap.put("/wx/cart/goodscount","anon");
        // 帮助
        filterChainDefinitionMap.put("/wx/issue/**","anon");
        // druid监控
        filterChainDefinitionMap.put("/druid/**","anon");
        // 其他
        filterChainDefinitionMap.put("/index","anon");

        /* 通过 @RequiresPermissions(value,logic) 指定具体的 permission */
        // 其余所有 url均需要认证（即登录）
        filterChainDefinitionMap.put("/**","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;
    }


    /*
     * 核心组件：SecurityManager
     * DefaultWebSecurityManager： shiro为java提供的 安全管理器
     * */
    @Bean
    public DefaultWebSecurityManager securityManager(AdminRealm adminRealm,WxRealm wxRealm,
                                                     DefaultWebSessionManager sessionManager){
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        // 配置 realm，最终提供给 （默认的）认证器&授权器
        // 默认 --> IniRealm，通过加载 ini文件获取权限，无法满足需求
        List<Realm> realms = new ArrayList<>();
        realms.add(adminRealm);
        realms.add(wxRealm);
        defaultWebSecurityManager.setRealms(realms);

        // 设置 sessionManager
        defaultWebSecurityManager.setSessionManager(sessionManager);

        // 设置认证器 和 授权器
        // 默认的也可以满足授权 --> ModularRealmAuthenticator，ModularRealmAuthorizer

        //defaultWebSecurityManager.setAuthenticator(authenticator);
        return defaultWebSecurityManager;
    }

    /*
     * Session管理
     *      提出：认证信息存储在session当中；前后端分离项目，每次发起新请求会跨域，重置session
     *      解决：通过sessionManager，保证跨域的请求也是使用同一个session，存储着相同的认真信息。
     * DefaultWebSessionManager 会自动校验 sessionId
     * */
    @Bean
    public DefaultWebSessionManager sessionManager(){
        // 使用自定义的 sessionManager
        DefaultWebSessionManager defaultWebSessionManager = new MarketSessionManager();
        //设置 session 过期时间，单位: milliseconds
        defaultWebSessionManager.setGlobalSessionTimeout(100*60*1000); // 100min
        return defaultWebSessionManager;
    }

    /*
     *提供的是注解的通知器,需要引入Aspectj依赖
     * 注册通知器：通过AspectJ-weaver实现，当使用注解给 Handler添加权限时候需要此组件
     * AuthorizationAttributeSourceAdvisor
     * */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager);
        return authorizationAttributeSourceAdvisor;
    }

    /*
    * 使用默认 认证器 authenticator
    * */
    /*@Bean
    public MarketAuthenticator authenticator(AdminRealm adminRealm, WxRealm wxRealm){
        MarketAuthenticator customAuthenticator = new MarketAuthenticator();
        ArrayList<Realm> realms = new ArrayList<>();
        realms.add(adminRealm);
        realms.add(wxRealm);
        customAuthenticator.setRealms(realms);
        return customAuthenticator;
    }*/
}
